001    /**
002     * Java Gui Builder - A library to build GUIs using an XML file.
003     * Copyright 2002, 2003 (C) François Beausoleil
004     *
005     * This library is free software; you can redistribute it and/or
006     * modify it under the terms of the GNU Lesser General Public
007     * License as published by the Free Software Foundation; either
008     * version 2.1 of the License, or (at your option) any later version.
009     *
010     * This library is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013     * Lesser General Public License for more details.
014     *
015     * You should have received a copy of the GNU Lesser General Public
016     * License along with this library; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018     */
019    
020    package jgb.handlers.swing;
021    
022    import jgb.builder.TagHandler;
023    import jgb.builder.WindowContext;
024    import org.xml.sax.SAXException;
025    
026    import java.lang.reflect.InvocationHandler;
027    import java.lang.reflect.Method;
028    import java.lang.reflect.Proxy;
029    import java.util.EventObject;
030    import java.util.Map;
031    
032    public class RegisterTagHandler extends AbstractTagHandler {
033        public static final String ATTR_METHOD = "method";
034        public static final String ATTR_MANAGER = "manager";
035        public static final String ATTR_EVENT = "event";
036    
037        protected void enterElement(Map atts) throws SAXException {
038            String className = (String)atts.get(ATTR_CLASS);
039            String eventName = (String)atts.get(ATTR_EVENT);
040            String managerName = (String)atts.get(ATTR_MANAGER);
041            String methodName = (String)atts.get(ATTR_METHOD);
042    
043            try {
044                Class listenerClass;
045                try {
046                    listenerClass = Class.forName(className);
047                } catch (ClassNotFoundException e) {
048                    try {
049                        listenerClass = Class.forName("java.awt.event." + className);
050                    } catch (ClassNotFoundException e1) {
051                        listenerClass = Class.forName("javax.swing.event." + className);
052                    }
053                }
054    
055                if (!listenerClass.isInterface()) {
056                    throwParsingException("register listener class must be an interface",
057                            new IllegalArgumentException(listenerClass.getName()));
058                }
059    
060                final Object managerObject = getObject(managerName);
061                final Method reflectedEventMethod = managerObject.getClass()
062                        .getMethod(methodName,
063                                new Class[]{
064                                    EventObject.class,
065                                    WindowContext.class}
066                        );
067                final Object listenerInstance = Proxy.newProxyInstance(
068                        this.getClass().getClassLoader(),
069                        new Class[]{listenerClass},
070                        new EventReflector(
071                                eventName, managerObject, reflectedEventMethod,
072                                (WindowContext)tagContext.get(TagHandler.WINDOW_CONTEXT_KEY)
073                        )
074                );
075    
076                final Object parentObject = getCurrentObject();
077                final Class parentObjectClass = parentObject.getClass();
078                final String listenerClassName;
079                final int lastDot = listenerClass.getName().lastIndexOf('.');
080                listenerClassName = listenerClass.getName().substring(1 + lastDot);
081                final Method addListenerMethod = parentObjectClass.getMethod(
082                        "add" + listenerClassName, new Class[]{listenerClass});
083                addListenerMethod.invoke(parentObject,
084                        new Object[]{listenerInstance});
085            } catch (SAXException e) {
086                throw e;
087            } catch (Exception e) {
088                throwParsingException("Unable to register event listener for event " +
089                        eventName + " on object " + getCurrentObjectId() + " for " +
090                        "class " + className, e);
091            }
092        }
093    
094        protected void exitElement() throws SAXException {
095        }
096    
097        private static final class EventReflector implements InvocationHandler {
098            private final String eventName;
099            private final Object managerObject;
100            private final Method reflectedEventMethod;
101            private final WindowContext windowContext;
102    
103            public EventReflector(String eventName, Object managerObject, Method reflectedEventMethod, WindowContext windowContext) {
104                this.eventName = eventName;
105                this.managerObject = managerObject;
106                this.reflectedEventMethod = reflectedEventMethod;
107                this.windowContext = windowContext;
108            }
109    
110            public Object invoke(Object proxy, Method method, Object[] args)
111                    throws Throwable {
112                if (eventName.equals(method.getName())) {
113                    reflectedEventMethod.invoke(
114                            managerObject,
115                            new Object[]{args[0], windowContext}
116                    );
117                }
118                return null;
119            }
120        }
121    }